home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_200 / 204_01 / gencode.c < prev    next >
Text File  |  1980-01-01  |  38KB  |  1,075 lines

  1. #include        <stdio.h>
  2. #include        "c.h"
  3. #include        "expr.h"
  4. #include        "gen.h"
  5. #include        "cglbdec.h"
  6.  
  7. /*
  8.  *    68000 C compiler
  9.  *
  10.  *    Copyright 1984, 1985, 1986 Matthew Brandt.
  11.  *  all commercial rights reserved.
  12.  *
  13.  *    This compiler is intended as an instructive tool for personal use. Any
  14.  *    use for profit without the written consent of the author is prohibited.
  15.  *
  16.  *    This compiler may be distributed freely for non-commercial use as long
  17.  *    as this notice stays intact. Please forward any enhancements or questions
  18.  *    to:
  19.  *
  20.  *        Matthew Brandt
  21.  *        Box 920337
  22.  *        Norcross, Ga 30092
  23.  */
  24.  
  25. /*
  26.  *      this module contains all of the code generation routines
  27.  *      for evaluating expressions and conditions.
  28.  */
  29.  
  30. extern struct amode     push[], pop[];
  31.  
  32. struct amode    *gen_expr();            /* forward declaration */
  33.  
  34. struct amode    *make_label(lab)
  35. /*
  36.  *      construct a reference node for an internal label number.
  37.  */
  38. int     lab;
  39. {       struct enode    *lnode;
  40.         struct amode    *ap;
  41.         lnode = xalloc(sizeof(struct enode));
  42.         lnode->nodetype = en_labcon;
  43.         lnode->v.i = lab;
  44.         ap = xalloc(sizeof(struct amode));
  45.         ap->mode = am_direct;
  46.         ap->offset = lnode;
  47.         return ap;
  48. }
  49.  
  50. struct amode    *make_immed(i)
  51. /*
  52.  *      make a node to reference an immediate value i.
  53.  */
  54. int     i;
  55. {       struct amode    *ap;
  56.         struct enode    *ep;
  57.         ep = xalloc(sizeof(struct enode));
  58.         ep->nodetype = en_icon;
  59.         ep->v.i = i;
  60.         ap = xalloc(sizeof(struct amode));
  61.         ap->mode = am_immed;
  62.         ap->offset = ep;
  63.         return ap;
  64. }
  65.  
  66. struct amode    *make_offset(node)
  67. /*
  68.  *      make a direct reference to a node.
  69.  */
  70. struct enode    *node;
  71. {       struct amode    *ap;
  72.         ap = xalloc(sizeof(struct amode));
  73.         ap->mode = am_direct;
  74.         ap->offset = node;
  75.         return ap;
  76. }
  77.         
  78. make_legal(ap,flags,size)
  79. /*
  80.  *      make_legal will coerce the addressing mode in ap1 into a
  81.  *      mode that is satisfactory for the flag word.
  82.  */
  83. struct amode    *ap;
  84. int             flags, size;
  85. {       struct amode    *ap2;
  86.         if( ((flags & F_VOL) == 0) || ap->tempflag )
  87.                 {
  88.                 switch( ap->mode )
  89.                         {
  90.                         case am_immed:
  91.                                 if( flags & F_IMMED )
  92.                                         return;         /* mode ok */
  93.                                 break;
  94.                         case am_areg:
  95.                                 if( flags & F_AREG )
  96.                                         return;
  97.                                 break;
  98.                         case am_dreg:
  99.                                 if( flags & F_DREG )
  100.                                         return;
  101.                                 break;
  102.                         case am_ind:    case am_indx:
  103.                         case am_indx2:  case am_xpc:
  104.                         case am_direct: case am_indx3:
  105.                                 if( flags & F_MEM )
  106.                                         return;
  107.                                 break;
  108.                         }
  109.                 }
  110.         if( flags & F_DREG )
  111.                 {
  112.                 freeop(ap);             /* maybe we can use it... */
  113.                 ap2 = temp_data();      /* allocate to dreg */
  114.                 gen_code(op_move,size,ap,ap2);
  115.                 ap->mode = am_dreg;
  116.                 ap->preg = ap2->preg;
  117.                 ap->deep = ap2->deep;
  118.                 ap->tempflag = 1;
  119.                 return;
  120.                 }
  121.         if( size == 1 )
  122.                 {
  123.                 freeop(ap);
  124.                 ap2 = temp_data();
  125.                 gen_code(op_move,1,ap,ap2);
  126.                 gen_code(op_ext,2,ap2,0);
  127.                 freeop(ap);
  128.                 ap->mode = ap2->mode;
  129.                 ap->preg = ap2->preg;
  130.                 ap->deep = ap2->deep;
  131.                 size = 2;
  132.                 }
  133.         freeop(ap);
  134.         ap2 = temp_addr();
  135.         gen_code(op_move,size,ap,ap2);
  136.         ap->mode = am_areg;
  137.         ap->preg = ap2->preg;
  138.         ap->deep = ap2->deep;
  139.         ap->tempflag = 1;
  140. }
  141.  
  142. do_extend(ap,isize,osize,flags)
  143. /*
  144.  *      if isize is not equal to osize then the operand ap will be
  145.  *      loaded into a register (if not already) and if osize is
  146.  *      greater than isize it will be extended to match.
  147.  */
  148. struct amode    *ap;
  149. int             isize, osize, flags;
  150. {       if( isize == osize )
  151.                 return;
  152.         if( ap->mode != am_areg && ap->mode != am_dreg )
  153.                 make_legal(ap,flags & (F_AREG | F_DREG),isize);
  154.         if( ap->mode == am_areg )
  155.                 return;         /* extend is automagic */
  156.         switch( isize )
  157.                 {
  158.                 case 1:
  159.                         gen_code(op_ext,2,ap,0);
  160.                 case 2:
  161.                         if( osize == 4 )
  162.                                 gen_code(op_ext,4,ap,0);
  163.                 }
  164. }
  165.  
  166. int     isshort(node)
  167. /*
  168.  *      return true if the node passed can be generated as a short
  169.  *      offset.
  170.  */
  171. struct enode    *node;
  172. {       return node->nodetype == en_icon &&
  173.                 (node->v.i >= -65536 && node->v.i <= 65535);
  174. }
  175.  
  176. int     isbyte(node)
  177. /*
  178.  *      return true if the node passed can be evaluated as a byte
  179.  *      offset.
  180.  */
  181. struct enode    *node;
  182. {       return node->nodetype == en_icon &&
  183.                 (-128 <= node->v.i && node->v.i <= 127);
  184. }
  185.  
  186. struct amode    *gen_index(node)
  187. /*
  188.  *      generate code to evaluate an index node (^+) and return
  189.  *      the addressing mode of the result. This routine takes no
  190.  *      flags since it always returns either am_ind or am_indx.
  191.  */
  192. struct enode    *node;
  193. {       struct amode    *ap1, *ap2;
  194.         if( node->v.p[0]->nodetype == en_tempref &&
  195.                 node->v.p[1]->nodetype == en_tempref &&
  196.                 ( node->v.p[0]->v.i >= 8 || node->v.p[1]->v.i >= 8 ))
  197.                 {       /* both nodes are registers, one is address */
  198.                 if( node->v.p[0]->v.i < 8 )
  199.                         {
  200.                         ap1 = gen_expr(node->v.p[1],F_AREG,4);
  201.                         ap1->sreg = node->v.p[0]->v.i;
  202.                         ap1->mode = am_indx2;   /* 0(Ax,Dx) */
  203.                         ap1->offset = makenode(en_icon,0,0);
  204.                         return ap1;
  205.                         }
  206.                 ap1 = gen_expr(node->v.p[0],F_AREG,4);
  207.                 ap2 = gen_expr(node->v.p[1],F_AREG | F_DREG,4);
  208.                 if( ap2->mode == am_dreg )
  209.                         {
  210.                         ap1->mode = am_indx2;
  211.                         ap1->sreg = ap2->preg;
  212.                         }
  213.                 else
  214.                         {
  215.                         ap1->mode = am_indx3;
  216.                         ap1->sreg = ap2->preg;
  217.                         }
  218.                 ap1->offset = makenode(en_icon,0,0);
  219.                 return ap1;
  220.                 }
  221.         ap1 = gen_expr(node->v.p[0],F_AREG | F_IMMED,4);
  222.         if( ap1->mode == am_immed && isshort(ap1->offset) )
  223.                 {
  224.                 ap2 = gen_expr(node->v.p[1],F_AREG,4);
  225.                 ap2->mode = am_indx;
  226.                 ap2->offset = ap1->offset;
  227.                 return ap2;
  228.                 }
  229.         ap2 = gen_expr(node->v.p[1],F_ALL,4);   /* get right op */
  230.         if( ap2->mode == am_immed && isshort(ap2->offset) &&
  231.             ap1->mode == am_areg ) /* make am_indx */
  232.                 {
  233.                 ap2->mode = am_indx;
  234.                 ap2->preg = ap1->preg;
  235.                 ap2->deep = ap1->deep;
  236.                 return ap2;
  237.                 }
  238.         validate(ap1);
  239.         make_legal(ap1,F_AREG | F_VOL,4);
  240.         gen_code(op_add,4,ap2,ap1);             /* add left to address reg */
  241.         ap1->mode = am_ind;             /* make indirect */
  242.         freeop(ap2);                    /* release any temps in ap2 */
  243.         return ap1;                     /* return indirect */
  244. }
  245.  
  246. struct